package cn.com.hhrcw.enterprise.web;

import cn.com.hhrcw.enterprise.params.StatisticsInfoParams;
import cn.com.hhrcw.enterprise.vo.*;
import cn.com.hhrcw.entity.EnInfo;
import cn.com.hhrcw.entity.OpDeliveryHistory;
import cn.com.hhrcw.entity.OpJob;
import cn.com.hhrcw.service.*;
import cn.com.hhrcw.statistics.IStatisticsService;
import cn.com.hhrcw.statistics.entity.Statistics;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.additional.query.impl.LambdaQueryChainWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.vo.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 招聘报表
 *
 * @program: recruit-boot-parent
 * @author: JD
 * @create: 2020-11-07 09:52
 **/
@RestController
@RequestMapping("/en/statistics")
@Slf4j
@Validated
public class StatisticsController {

    @Autowired
    private IOpJobService jobService;

    @Autowired
    JdbcTemplate jdbcTemplate;

    @Autowired
    ISysUserDepartService userDepartService;

    @Autowired
    private IEnInfoService enInfoService;

    @Autowired
    private IOpDeliveryHistoryService deliveryHistoryService;

    @Autowired
    private IOpEntryHistoryService entryHistoryService;

    @Autowired
    private IStatisticsService statisticsService;

    /**
     * 招聘报表-列表
     *
     * @param params
     * @return
     */
    @GetMapping("/jobInfos")
    @AutoLog(logType = 2, ty = "visit", value = "招聘报表")
    public Result<Page<JobsStatisticsVO>> getStatisticsInfo(StatisticsInfoParams params) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryChainWrapper<OpJob> wrapper = this.jobService.lambdaQuery();
        wrapper.eq(OpJob::getCompanyId, loginUser.getCompanyId());
        if (StringUtils.isNotBlank(params.getJobName())) {
            wrapper.like(OpJob::getJobName, params.getJobName());
        }
        if (params.getStartTime() != null) {
            wrapper.ge(OpJob::getCreateTime, params.getStartTime());
        }
        if (params.getEndTime() != null) {
            wrapper.le(OpJob::getCreateTime, cn.hutool.core.date.DateUtil.endOfDay(cn.hutool.core.date.DateUtil.parse(params.getEndTime())));
        }
        IPage<OpJob> page = wrapper.eq(OpJob::getDelFlag, false).page(params.page());
        IPage<JobsStatisticsVO> convert = page.convert(e -> {
            Statistics statistics = statisticsService.queryByJob(e.getId());
            JobsStatisticsVO vo = new JobsStatisticsVO();
            EnInfo enInfo = enInfoService.getById(e.getCompanyId());
            if (enInfo == null) {
                enInfo = new EnInfo();
            }
            vo.setComName(enInfo.getEnName());
            vo.setJobId(e.getId());
            vo.setJobName(e.getJobName());
            vo.setJobTime(e.getCreateTime());
            vo.setState(e.getDelFlag() ? 2 : e.getRecruitmentState());
            vo.setPlaneCount(statistics.getRecruitment());

            vo.setDeCount(statistics.getTotal());
            vo.setScreenCount(statistics.getTotal() - statistics.getFilterBySystem());
            vo.setFirstScrCount(statistics.getFilterFirst());

            vo.setViewCount(statistics.getAlreadyInterview());
            vo.setEntryCount(statistics.getAccession());
            vo.setNotCount(statistics.getRemaining());
            vo.setOfferCount(statistics.getOffer());
            vo.setCompletionRate(NumberUtil.round(NumberUtil.div(vo.getEntryCount(), e.getNeedCount()), 2));
            return vo;
        });
        return Result.ok((Page) convert);
    }

    /**
     * 招聘报表-招聘环节分析-招聘漏斗
     *
     * @param dataType 查询范围,true本年度，false或者空查询所有
     * @return
     */
    @GetMapping("/funnelInfo")
    @AutoLog(logType = 2, ty = "visit", value = "招聘漏斗")
    public Result<FunnelInfoVO> funnelInfo(Boolean dataType) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Statistics statistics = statisticsService.queryByCompany(loginUser.getCompanyId());
        FunnelInfoVO vo = new FunnelInfoVO();
        vo.setScreenCount(statistics.getTotal() - statistics.getFilterBySystem());
        vo.setFirstScreenCount(statistics.getFilterFirst());
        vo.setInviteViewCount(statistics.getInterview());
        vo.setJoinViewCount(statistics.getAlreadyInterview());
        vo.setSimulationCount(statistics.getOffer() - statistics.getEliminateInterview());
        vo.setOfferCount(statistics.getOffer());
        vo.setEntryCount(statistics.getAccession());
        return Result.ok(vo);
    }

    /**
     * 招聘报表-流失淘汰环节分析
     *
     * @param dataType 查询范围,true本年度，false或者空查询所有
     * @return
     */
    @GetMapping("/eliminateInfo")
    @AutoLog(logType = 2, ty = "visit", value = "淘汰环节分析")
    public Result<EliminateInfo> eliminateInfo(Boolean dataType) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        Statistics statistics = statisticsService.queryByCompany(sysUser.getCompanyId());
        EliminateInfo info = new EliminateInfo();
        info.setPreliminary(BigDecimal.ZERO);
        info.setView(BigDecimal.ZERO);
        info.setSys(BigDecimal.ZERO);

        //通过系统筛选
        int pass = statistics.getTotal() - statistics.getFilterBySystem();
        //被系统过滤
        int sys = statistics.getFilterBySystem();
        //初筛淘汰
        int first = statistics.getEliminateFilterFirst();
        //面试淘汰
        int view = statistics.getEliminateInterview();
        int viewTotal = statistics.getOffer();
        if (pass > 0) {
            info.setPreliminary(NumberUtil.round(NumberUtil.div(first, pass), 2));
        }
        if (viewTotal > 0) {
            info.setView(NumberUtil.round(NumberUtil.div(view, viewTotal), 2));
        }
        if (statistics.getTotal() == null || statistics.getTotal() == 0) {
            info.setSys(BigDecimal.ZERO);
        } else {
            info.setSys(NumberUtil.round(NumberUtil.div(sys, statistics.getTotal().intValue()), 2));
        }


        return Result.ok(info);
    }

    /**
     * 招聘报表-招聘环节分析-各个职位信息统计
     *
     * @param params
     * @return
     */
    @GetMapping("/jobAnalysisInfo")
    @AutoLog(logType = 2, ty = "visit", value = "各职位信息统计")
    public Result<Page<JobAnalysisVO>> jobAnalysisInfo(StatisticsInfoParams params) {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        LambdaQueryChainWrapper<OpJob> wrapper = this.jobService.lambdaQuery();
        wrapper.eq(OpJob::getCompanyId, sysUser.getCompanyId());
        if (StringUtils.isNotBlank(params.getJobName())) {
            wrapper.like(OpJob::getJobName, params.getJobName());
        }
        if (params.getStartTime() != null) {
            wrapper.ge(OpJob::getCreateTime, params.getStartTime());
        }
        if (params.getEndTime() != null) {
            wrapper.le(OpJob::getCreateTime, cn.hutool.core.date.DateUtil.endOfDay(cn.hutool.core.date.DateUtil.parse(params.getEndTime())));
        }
        IPage<OpJob> page = wrapper.eq(OpJob::getDelFlag, false).page(params.page());
        IPage<JobAnalysisVO> convert = page.convert(e -> {
            JobAnalysisVO vo = new JobAnalysisVO();
            EnInfo enInfo = enInfoService.getById(e.getCompanyId());
            if (enInfo == null) {
                enInfo = new EnInfo();
            }
            vo.setJobId(e.getId());
            vo.setJobName(e.getJobName());
            vo.setJobTime(e.getCreateTime());
            vo.setState(e.getDelFlag() ? 2 : e.getRecruitmentState());
            vo.setFirstScrRate(BigDecimal.ZERO);
            vo.setViewRate(BigDecimal.ZERO);
            vo.setPositionRate(BigDecimal.ZERO);
            vo.setAdoptRate(BigDecimal.ZERO);
            vo.setEmployRate(BigDecimal.ZERO);
            vo.setLossRate(BigDecimal.ZERO);

            Statistics statistics = statisticsService.queryByJob(e.getId());

            //通过初筛
            long firstScrCount = statistics.getFilterFirst();
            vo.setFirstScrCount((int) firstScrCount);
            //初筛通过率
            if (statistics.getPassFilterSystem() > 0) {
                vo.setFirstScrRate(NumberUtil.round(NumberUtil.div(firstScrCount, statistics.getPassFilterSystem().intValue()), 2));
            }
            //面试
            vo.setViewCount(statistics.getInterview());
            //邀约面试率   面试邀请数量/通过初筛数量
            if (firstScrCount > 0) {
                vo.setViewRate(NumberUtil.round(NumberUtil.div(statistics.getInterview().intValue(), firstScrCount), 2));
            }
            //已面试数量
            long alreadyViewCount = statistics.getAlreadyInterview();
            vo.setAlreadyViewCount((int) alreadyViewCount);
            //接收面试数量
            long accept = statistics.getAcceptInterview();
            //面试到场率   已面试数量/接收面试数量
            if (accept > 0) {
                vo.setPresentRate(NumberUtil.round(NumberUtil.div(alreadyViewCount, accept), 2));
            }
            //通过面试数量
            long adoptCount = statistics.getPassInterview();
            vo.setAdoptCount((int) adoptCount);
            //面试通过率  通过面试数量/已面试数量
            if (alreadyViewCount > 0) {
                vo.setAdoptRate(NumberUtil.round(NumberUtil.div(adoptCount, alreadyViewCount), 2));
            }
            //录用
            vo.setEmployCount(statistics.getOffer());
            //录用率  入职邀请数量/面试总数量
            if (statistics.getOffer() > 0) {
                vo.setEmployRate(NumberUtil.round(NumberUtil.div(statistics.getOffer(), statistics.getInterview()), 2));
            }
            long entryCount = statistics.getAccession();
            vo.setEntryCount((int) entryCount);
            long entryAccept = statistics.getAcceptOffer();
            //到岗率   已入职数量/接受入职邀请数量
            if (entryAccept > 0) {
                vo.setPositionRate(NumberUtil.round(NumberUtil.div(entryCount, entryAccept), 2));
            }
            long lossCount = statistics.getRejectOffer();
            vo.setLossCount((int) lossCount);
            //流失率   未接受入职邀请数量/总入职邀请数量
            if (statistics.getOffer() > 0) {
                vo.setLossRate(NumberUtil.round(NumberUtil.div(lossCount, statistics.getOffer().intValue()), 2));
            }
            return vo;
        });
        return Result.ok((Page) convert);
    }

    /**
     * 招聘报表-招聘环节分析-初筛淘汰环节分析
     *
     * @param dataType 查询范围，true本年度，false或者空查询所有
     * @return
     */
    @GetMapping("/eliminateReasonInfo")
    @AutoLog(logType = 2, ty = "visit", value = "初筛淘汰环节分析")
    public Result<EliminateReasonVO> eliminateReasonInfo(Boolean dataType) {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        EliminateReasonVO res = new EliminateReasonVO();
        res.setExperienceCount(0);
        res.setTechnologyCount(0);
        res.setSalaryCount(0);
        res.setEducationCount(0);
        res.setIndustryCount(0);
        res.setTypeCount(0);

        List<OpJob> jobs = jobService.lambdaQuery().eq(OpJob::getCompanyId, loginUser.getCompanyId()).eq(OpJob::getDelFlag, false).eq(OpJob::getRecruitmentState, 0).select(OpJob::getId).list();

        if (!CollectionUtils.isEmpty(jobs)) {
            List<String> jobIds = new ArrayList<>();
            jobs.forEach(e -> {
                jobIds.add(e.getId());
            });
            List<OpDeliveryHistory> list = this.deliveryHistoryService.lambdaQuery().in(OpDeliveryHistory::getJobId, jobIds).eq(OpDeliveryHistory::getDelFlag, false).eq(OpDeliveryHistory::getState, 2).isNotNull(OpDeliveryHistory::getInappropriateInfo).list();
            if (CollUtil.isEmpty(list)) {
                return Result.ok(res);
            }
        /*
            不合适原因
            0:工作经验不满足要求数量
            1:技术不符合岗位要求
            2:薪资不匹配
            3:学历不匹配
            4:行业不匹配
            5:招聘类型不匹配
            * */
            Long experienceCount = list.stream().filter(e -> StrUtil.equals(e.getInappropriateInfo(), "0")).count();
            Long technologyCount = list.stream().filter(e -> StrUtil.equals(e.getInappropriateInfo(), "1")).count();
            Long salaryCount = list.stream().filter(e -> StrUtil.equals(e.getInappropriateInfo(), "2")).count();
            Long educationCount = list.stream().filter(e -> StrUtil.equals(e.getInappropriateInfo(), "3")).count();
            Long industryCount = list.stream().filter(e -> StrUtil.equals(e.getInappropriateInfo(), "4")).count();
            Long typeCount = list.stream().filter(e -> StrUtil.equals(e.getInappropriateInfo(), "5")).count();
            res.setExperienceCount(experienceCount.intValue());
            res.setTechnologyCount(technologyCount.intValue());
            res.setSalaryCount(salaryCount.intValue());
            res.setEducationCount(educationCount.intValue());
            res.setIndustryCount(industryCount.intValue());
            res.setTypeCount(typeCount.intValue());
        }
        return Result.ok(res);
    }
}
